package main

/*
* Content: Context-传递共享数据、通过 Context优雅的退出 Groutine
* --------------------------------------------------
* Context - Go语言中文文档: https://topgoer.cn/docs/golang/chapter11-10
* 从使用角度浅谈 Go context: https://juejin.cn/post/7173094636330680327
 */

import (
	"context"
	"fmt"
	"sync"
	"time"
)

var wg3 sync.WaitGroup

func worker1(ctx context.Context) {
	go worker2(ctx)
LOOP:
	for {
		fmt.Println("worker")
		time.Sleep(time.Second)

		select {
		case <-ctx.Done(): // 等待上级通知
			break LOOP
		default:
		}
	}
	wg3.Done()
}

func worker2(ctx context.Context) {
LOOP:
	for {
		fmt.Println("worker2")
		time.Sleep(time.Second)

		select {
		case <-ctx.Done(): // 等待上级通知
			break LOOP
		default:
		}
	}
}

func MyBagContext() {

	// Context-传递共享数据
	fmt.Println("--------------------Context-传递共享数据--------------------")

	//上下文默认值，所有其他的上下文都从他衍生。通常用于main函数、初始化、测试或者顶级上下文
	ctx := context.Background()
	s, ok := ctx.Value("name").(string)
	if !ok {
		fmt.Println("nil")
	} else {
		fmt.Println("直接获取到的name: ", s)
	}

	//基于某个 context 创建并存储对应的上下文信息。
	ctx = context.WithValue(ctx, "name", "XieQingZhao")
	s, _ = ctx.Value("name").(string)
	fmt.Println("赋值之后的name: ", s)

	// 通过 Context优雅的退出 Groutine
	fmt.Println("--------------------通过 Context优雅的退出 Groutine--------------------")

	// ctx: 上下文    cancel: 取消函数 (是一个函数)
	ctx, cancel := context.WithCancel(context.Background())

	wg3.Add(1)
	go worker1(ctx)

	// 睡眠3秒, 然后再继续执行
	time.Sleep(time.Second * 3)

	cancel() // 通知子goroutine结束

	wg3.Wait()

	fmt.Println("over")
}
